/*
 * Copyright (c) 2011, Yawning <yawninglol at gmail.com>
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 *   * Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   * Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in the
 *     documentation and/or other materials provided with the distribution.
 *
 *   * Neither the name of the Mew Developers nor the
 *     names of its contributors may be used to endorse or promote products
 *     derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
 * THE POSSIBILITY OF SUCH DAMAGE.
 */

package yawning.mew.pivot.protwarrior;

import org.apache.pivot.beans.BXML;
import org.apache.pivot.beans.BXMLSerializer;
import org.apache.pivot.collections.HashMap;
import org.apache.pivot.collections.List;
import org.apache.pivot.collections.Map;
import org.apache.pivot.json.JSON;
import org.apache.pivot.serialization.SerializationException;
import org.apache.pivot.wtk.Component;
import org.apache.pivot.wtk.TableView;
import org.apache.pivot.wtk.Spinner;

import yawning.mew.character.Clazz;
import yawning.mew.character.Glyph;
import yawning.mew.character.Talent;
import yawning.mew.character.Toon;
import yawning.mew.pivot.MewPivotTalentBase;
import yawning.mew.pivot.MewTableViewMouseButtonListener;

import java.io.IOException;
import java.util.Properties;

/**
 * Mew Pivot Prot Warrior Talent/Glyph specific UI components.
 *
 * @author Yawning <yawninglol at gmail.com>
 */
public class Talents extends MewPivotTalentBase {
	private Component mComponent;

	@BXML private TableView glyphTable = null;

	// Protection talents
	@BXML private Spinner talentIncite;
	@BXML private Spinner talentToughness;
	@BXML private Spinner talentBloodAndThunder;
	@BXML private Spinner talentShieldSpecialization;
	@BXML private Spinner talentShieldMastery;
	@BXML private Spinner talentHoldTheLine;
	@BXML private Spinner talentGagOrder;
	@BXML private Spinner talentLastStand;
	@BXML private Spinner talentConcussionBlow;
	@BXML private Spinner talentBastionOfDefense;
	@BXML private Spinner talentWarbringer;
	@BXML private Spinner talentImprovedRevenge;
	@BXML private Spinner talentDevastate;
	@BXML private Spinner talentImpendingVictory;
	@BXML private Spinner talentThunderstruck;
	@BXML private Spinner talentVigilance;
	@BXML private Spinner talentHeavyRepercussions;
	@BXML private Spinner talentSafeguard;
	@BXML private Spinner talentSwordAndBoard;
	@BXML private Spinner talentShockwave;

	// Fury talents
	@BXML private Spinner talentBloodCraze;
	@BXML private Spinner talentBattleTrance;
	@BXML private Spinner talentCruelty;
	@BXML private Spinner talentBoomingVoice;
	@BXML private Spinner talentRudeInterruption;

	// Arms talents
	@BXML private Spinner talentWarAcademy;
	@BXML private Spinner talentFieldDressing;
	@BXML private Spinner talentBlitz;
	@BXML private Spinner talentDeepWounds;
	@BXML private Spinner talentDrumsOfWar;

	public Talents() {
		BXMLSerializer bxmlSerializer = new BXMLSerializer();

		try {
			mComponent = (Component) bxmlSerializer.readObject(getClass().getResource("Talents.bxml"));
		} catch (IOException e) {
			e.printStackTrace();
		} catch (SerializationException e) {
			e.printStackTrace();
		}

		bxmlSerializer.bind(this);

		glyphTable.getComponentMouseButtonListeners().add(new MewTableViewMouseButtonListener());
	}

	public Component getComponent() {
		return mComponent;
	}

	@SuppressWarnings("unchecked")
	public void onLoad(Map<String,Object> backingStore) {
		Map<String,?> tmp;

		tmp = JSON.get(backingStore, "talents");

		if (tmp.containsKey("Talent.Incite")) { talentIncite.setSelectedIndex((Integer) tmp.get("Talent.Incite")); }
		if (tmp.containsKey("Talent.Toughness")) { talentToughness.setSelectedIndex((Integer) tmp.get("Talent.Toughness")); }
		if (tmp.containsKey("Talent.BloodAndThunder")) { talentBloodAndThunder.setSelectedIndex((Integer) tmp.get("Talent.BloodAndThunder")); }
		if (tmp.containsKey("Talent.ShieldSpecialization")) { talentShieldSpecialization.setSelectedIndex((Integer) tmp.get("Talent.ShieldSpecialization")); }
		if (tmp.containsKey("Talent.ShieldMastery")) { talentShieldMastery.setSelectedIndex((Integer) tmp.get("Talent.ShieldMastery")); }
		if (tmp.containsKey("Talent.HoldTheLine")) { talentHoldTheLine.setSelectedIndex((Integer) tmp.get("Talent.HoldTheLine")); }
		if (tmp.containsKey("Talent.GagOrder")) { talentGagOrder.setSelectedIndex((Integer) tmp.get("Talent.GagOrder")); }
		if (tmp.containsKey("Talent.LastStand")) { talentLastStand.setSelectedIndex((Integer) tmp.get("Talent.LastStand")); }
		if (tmp.containsKey("Talent.ConcussionBlow")) { talentConcussionBlow.setSelectedIndex((Integer) tmp.get("Talent.ConcussionBlow")); }
		if (tmp.containsKey("Talent.BastionOfDefense")) { talentBastionOfDefense.setSelectedIndex((Integer) tmp.get("Talent.BastionOfDefense")); }
		if (tmp.containsKey("Talent.Warbringer")) { talentWarbringer.setSelectedIndex((Integer) tmp.get("Talent.Warbringer")); }
		if (tmp.containsKey("Talent.ImprovedRevenge")) { talentImprovedRevenge.setSelectedIndex((Integer) tmp.get("Talent.ImprovedRevenge")); }
		if (tmp.containsKey("Talent.Devastate")) { talentDevastate.setSelectedIndex((Integer) tmp.get("Talent.Devastate")); }
		if (tmp.containsKey("Talent.ImpendingVictory")) { talentImpendingVictory.setSelectedIndex((Integer) tmp.get("Talent.ImpendingVictory")); }
		if (tmp.containsKey("Talent.Thunderstruck")) { talentThunderstruck.setSelectedIndex((Integer) tmp.get("Talent.Thunderstruck")); }
		if (tmp.containsKey("Talent.Vigilance")) { talentVigilance.setSelectedIndex((Integer) tmp.get("Talent.Vigilance")); }
		if (tmp.containsKey("Talent.HeavyRepercussions")) { talentHeavyRepercussions.setSelectedIndex((Integer) tmp.get("Talent.HeavyRepercussions")); }
		if (tmp.containsKey("Talent.Safeguard")) { talentSafeguard.setSelectedIndex((Integer) tmp.get("Talent.Safeguard")); }
		if (tmp.containsKey("Talent.SwordAndBoard")) { talentSwordAndBoard.setSelectedIndex((Integer) tmp.get("Talent.SwordAndBoard")); }
		if (tmp.containsKey("Talent.Shockwave")) { talentShockwave.setSelectedIndex((Integer) tmp.get("Talent.Shockwave")); }

		if (tmp.containsKey("Talent.BloodCraze")) { talentBloodCraze.setSelectedIndex((Integer) tmp.get("Talent.BloodCraze")); }
		if (tmp.containsKey("Talent.BattleTrance")) { talentBattleTrance.setSelectedIndex((Integer) tmp.get("Talent.BattleTrance")); }
		if (tmp.containsKey("Talent.Cruelty")) { talentCruelty.setSelectedIndex((Integer) tmp.get("Talent.Cruelty")); }
		if (tmp.containsKey("Talent.BoomingVoice")) { talentBoomingVoice.setSelectedIndex((Integer) tmp.get("Talent.BoomingVoice")); }
		if (tmp.containsKey("Talent.RudeInterruption")) { talentRudeInterruption.setSelectedIndex((Integer) tmp.get("Talent.RudeInterruption")); }

		if (tmp.containsKey("Talent.WarAcademy")) { talentWarAcademy.setSelectedIndex((Integer) tmp.get("Talent.WarAcademy")); }
		if (tmp.containsKey("Talent.FieldDressing")) { talentFieldDressing.setSelectedIndex((Integer) tmp.get("Talent.FieldDressing")); }
		if (tmp.containsKey("Talent.Blitz")) { talentBlitz.setSelectedIndex((Integer) tmp.get("Talent.Blitz")); }
		if (tmp.containsKey("Talent.DeepWounds")) { talentDeepWounds.setSelectedIndex((Integer) tmp.get("Talent.DeepWounds")); }
		if (tmp.containsKey("Talent.DrumsOfWar")) { talentDrumsOfWar.setSelectedIndex((Integer) tmp.get("Talent.DrumsOfWar")); }

		tmp = JSON.get(backingStore, "glyphs");
		if (tmp != null) {
			for (Map<String,Object> row : (List<Map<String,Object>>) glyphTable.getTableData()) {
				String key = JSON.get(row, "prop");

				if (tmp.containsKey(key)) {
					boolean enabled = (Boolean) tmp.get(key);
					JSON.put(row, "enabled", enabled);
				}
			}
		}
	}

	@SuppressWarnings("unchecked")
	public void onSave(Map<String,Object> backingStore) {
		HashMap<String,Object> tmp;

		tmp = new HashMap<String,Object>();
		tmp.put("Talent.Incite", (Integer) talentIncite.getSelectedIndex());
		tmp.put("Talent.Toughness", (Integer) talentToughness.getSelectedIndex());
		tmp.put("Talent.BloodAndThunder", (Integer) talentBloodAndThunder.getSelectedIndex());
		tmp.put("Talent.ShieldSpecialization", (Integer) talentShieldSpecialization.getSelectedIndex());
		tmp.put("Talent.ShieldMastery", (Integer) talentShieldMastery.getSelectedIndex());
		tmp.put("Talent.HoldTheLine", (Integer) talentHoldTheLine.getSelectedIndex());
		tmp.put("Talent.GagOrder", (Integer) talentGagOrder.getSelectedIndex());
		tmp.put("Talent.LastStand", (Integer) talentLastStand.getSelectedIndex());
		tmp.put("Talent.ConcussionBlow", (Integer) talentConcussionBlow.getSelectedIndex());
		tmp.put("Talent.BastionOfDefense", (Integer) talentBastionOfDefense.getSelectedIndex());
		tmp.put("Talent.Warbringer", (Integer) talentWarbringer.getSelectedIndex());
		tmp.put("Talent.ImprovedRevenge", (Integer) talentImprovedRevenge.getSelectedIndex());
		tmp.put("Talent.Devastate", (Integer) talentDevastate.getSelectedIndex());
		tmp.put("Talent.ImpendingVictory", (Integer) talentImpendingVictory.getSelectedIndex());
		tmp.put("Talent.Thunderstruck", (Integer) talentThunderstruck.getSelectedIndex());
		tmp.put("Talent.Vigilance", (Integer) talentVigilance.getSelectedIndex());
		tmp.put("Talent.HeavyRepercussions", (Integer) talentHeavyRepercussions.getSelectedIndex());
		tmp.put("Talent.Safeguard", (Integer) talentSafeguard.getSelectedIndex());
		tmp.put("Talent.SwordAndBoard", (Integer) talentSwordAndBoard.getSelectedIndex());
		tmp.put("Talent.Shockwave", (Integer) talentShockwave.getSelectedIndex());

		tmp.put("Talent.BloodCraze", (Integer) talentBloodCraze.getSelectedIndex());
		tmp.put("Talent.BattleTrance", (Integer) talentBattleTrance.getSelectedIndex());
		tmp.put("Talent.Cruelty", (Integer) talentCruelty.getSelectedIndex());
		tmp.put("Talent.BoomingVoice", (Integer) talentBoomingVoice.getSelectedIndex());
		tmp.put("Talent.RudeInterruption", (Integer) talentRudeInterruption.getSelectedIndex());

		tmp.put("Talent.WarAcademy", (Integer) talentWarAcademy.getSelectedIndex());
		tmp.put("Talent.FieldDressing", (Integer) talentFieldDressing.getSelectedIndex());
		tmp.put("Talent.Blitz", (Integer) talentBlitz.getSelectedIndex());
		tmp.put("Talent.DeepWounds", (Integer) talentDeepWounds.getSelectedIndex());
		tmp.put("Talent.DrumsOfWar", (Integer) talentDrumsOfWar.getSelectedIndex());
		JSON.put(backingStore, "talents", tmp);

		tmp = new HashMap<String,Object>();
		for (Map<String,Object> row : (List<Map<String,Object>>) glyphTable.getTableData()) {
			String key = JSON.get(row, "prop");
			boolean value = (Boolean) JSON.get(row, "enabled");

			tmp.put(key, value);
		}
		JSON.put(backingStore, "glyphs", tmp);
	}

	@SuppressWarnings("unchecked")
	public Properties toProperties() {
		Properties rval = new Properties();

		// Talents
		rval.setProperty("Talent.Incite", Integer.toString(talentIncite.getSelectedIndex()));
		rval.setProperty("Talent.Toughness", Integer.toString(talentToughness.getSelectedIndex()));
		rval.setProperty("Talent.Blood and Thunder", Integer.toString(talentBloodAndThunder.getSelectedIndex()));
		rval.setProperty("Talent.Shield Specialization", Integer.toString(talentShieldSpecialization.getSelectedIndex()));
		rval.setProperty("Talent.Shield Mastery", Integer.toString(talentShieldMastery.getSelectedIndex()));
		rval.setProperty("Talent.Hold the Line", Integer.toString(talentHoldTheLine.getSelectedIndex()));
		rval.setProperty("Talent.Gag Order", Integer.toString(talentGagOrder.getSelectedIndex()));
		rval.setProperty("Talent.Last Stand", Integer.toString(talentLastStand.getSelectedIndex()));
		rval.setProperty("Talent.Concussion Blow", Integer.toString(talentConcussionBlow.getSelectedIndex()));
		rval.setProperty("Talent.Bastion of Defense", Integer.toString(talentBastionOfDefense.getSelectedIndex()));
		rval.setProperty("Talent.Warbringer", Integer.toString(talentWarbringer.getSelectedIndex()));
		rval.setProperty("Talent.Improved Revenge", Integer.toString(talentImprovedRevenge.getSelectedIndex()));
		rval.setProperty("Talent.Devastate", Integer.toString(talentDevastate.getSelectedIndex()));
		rval.setProperty("Talent.Impending Victory", Integer.toString(talentImpendingVictory.getSelectedIndex()));
		rval.setProperty("Talent.Thunderstruck", Integer.toString(talentThunderstruck.getSelectedIndex()));
		rval.setProperty("Talent.Vigilance", Integer.toString(talentVigilance.getSelectedIndex()));
		rval.setProperty("Talent.Heavy Repercussions", Integer.toString(talentHeavyRepercussions.getSelectedIndex()));
		rval.setProperty("Talent.Safeguard", Integer.toString(talentSafeguard.getSelectedIndex()));
		rval.setProperty("Talent.Sword and Board", Integer.toString(talentSwordAndBoard.getSelectedIndex()));
		rval.setProperty("Talent.Shockwave", Integer.toString(talentShockwave.getSelectedIndex()));

		rval.setProperty("Talent.Blood Craze", Integer.toString(talentBloodCraze.getSelectedIndex()));
		rval.setProperty("Talent.Battle Trance", Integer.toString(talentBattleTrance.getSelectedIndex()));
		rval.setProperty("Talent.Cruelty", Integer.toString(talentCruelty.getSelectedIndex()));
		rval.setProperty("Talent.Booming Voice", Integer.toString(talentBoomingVoice.getSelectedIndex()));
		rval.setProperty("Talent.Rude Interruption", Integer.toString(talentRudeInterruption.getSelectedIndex()));

		rval.setProperty("Talent.War Academy", Integer.toString(talentWarAcademy.getSelectedIndex()));
		rval.setProperty("Talent.Field Dressing", Integer.toString(talentFieldDressing.getSelectedIndex()));
		rval.setProperty("Talent.Blitz", Integer.toString(talentBlitz.getSelectedIndex()));
		rval.setProperty("Talent.Deep Wounds", Integer.toString(talentDeepWounds.getSelectedIndex()));
		rval.setProperty("Talent.Drums of War", Integer.toString(talentDrumsOfWar.getSelectedIndex()));

		// Glyphs
		for (Map<String,Object> row : (List<Map<String,Object>>) glyphTable.getTableData()) {
			String key = JSON.get(row, "name");
			boolean value = (Boolean) JSON.get(row, "enabled");

			rval.setProperty(key, Boolean.toString(value));
		}

		// TalentSpec should be "Protection" by default.
		rval.setProperty("TalentSpec", "Protection");

		return rval;
	}

	@SuppressWarnings("unchecked")
	public void onImport(Toon toon) {
		// Import talents.
		Clazz c = Clazz.WARRIOR;
		talentIncite.setSelectedIndex(toon.getTalent(Talent.getByName(c, "Incite")));
		talentToughness.setSelectedIndex(toon.getTalent(Talent.getByName(c, "Toughness")));
		talentBloodAndThunder.setSelectedIndex(toon.getTalent(Talent.getByName(c, "Blood and Thunder")));
		talentShieldSpecialization.setSelectedIndex(toon.getTalent(Talent.getByName(c, "Shield Specialization")));
		talentShieldMastery.setSelectedIndex(toon.getTalent(Talent.getByName(c, "Shield Mastery")));
		talentHoldTheLine.setSelectedIndex(toon.getTalent(Talent.getByName(c, "Hold the Line")));
		talentGagOrder.setSelectedIndex(toon.getTalent(Talent.getByName(c, "Gag Order")));
		talentLastStand.setSelectedIndex(toon.getTalent(Talent.getByName(c, "Last Stand")));
		talentConcussionBlow.setSelectedIndex(toon.getTalent(Talent.getByName(c, "Concussion Blow")));
		talentBastionOfDefense.setSelectedIndex(toon.getTalent(Talent.getByName(c, "Bastion of Defense")));
		talentWarbringer.setSelectedIndex(toon.getTalent(Talent.getByName(c, "Warbringer")));
		talentImprovedRevenge.setSelectedIndex(toon.getTalent(Talent.getByName(c, "Improved Revenge")));
		talentDevastate.setSelectedIndex(toon.getTalent(Talent.getByName(c, "Devastate")));
		talentImpendingVictory.setSelectedIndex(toon.getTalent(Talent.getByName(c, "Impending Victory")));
		talentThunderstruck.setSelectedIndex(toon.getTalent(Talent.getByName(c, "Thunderstruck")));
		talentVigilance.setSelectedIndex(toon.getTalent(Talent.getByName(c, "Vigilance")));
		talentHeavyRepercussions.setSelectedIndex(toon.getTalent(Talent.getByName(c, "Heavy Repercussions")));
		talentSafeguard.setSelectedIndex(toon.getTalent(Talent.getByName(c, "Safeguard")));
		talentSwordAndBoard.setSelectedIndex(toon.getTalent(Talent.getByName(c, "Sword And Board")));
		talentShockwave.setSelectedIndex(toon.getTalent(Talent.getByName(c, "Shockwave")));

		talentBloodCraze.setSelectedIndex(toon.getTalent(Talent.getByName(c, "Blood Craze")));
		talentBattleTrance.setSelectedIndex(toon.getTalent(Talent.getByName(c, "Battle Trance")));
		talentCruelty.setSelectedIndex(toon.getTalent(Talent.getByName(c, "Cruelty")));
		talentBoomingVoice.setSelectedIndex(toon.getTalent(Talent.getByName(c, "Booming Voice")));
		talentRudeInterruption.setSelectedIndex(toon.getTalent(Talent.getByName(c, "Rude Interruption")));

		talentWarAcademy.setSelectedIndex(toon.getTalent(Talent.getByName(c, "War Academy")));
		talentFieldDressing.setSelectedIndex(toon.getTalent(Talent.getByName(c, "Field Dressing")));
		talentBlitz.setSelectedIndex(toon.getTalent(Talent.getByName(c, "Blitz")));
		talentDeepWounds.setSelectedIndex(toon.getTalent(Talent.getByName(c, "Deep Wounds")));
		talentDrumsOfWar.setSelectedIndex(toon.getTalent(Talent.getByName(c, "Drums of War")));

		// Handle supported glyphs.
		for (Map<String,Object> row : (List<Map<String,Object>>) glyphTable.getTableData()) {
			int idx = ((List<Map<String,Object>>)glyphTable.getTableData()).indexOf(row);
			if (toon.hasGlyph(Glyph.getByName((String) JSON.get(row, "name")))) {
				JSON.put(row, "enabled", true);
			} else {
				JSON.put(row, "enabled", false);
			}
			((List<Map<String,Object>>)glyphTable.getTableData()).update(idx, row);
		}
	}
}
